package com.agileboot.domain.airport.dashboard.db;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;

@Service
public class SirStatisticsServiceImpl implements ISirStatisticsService {

    @Autowired
    private SirStatisticsMapper statisticsMapper;

    @Override
    public List<SirStatisticsDTO> getMonthlyCoreStatistics() {
        LocalDate today = LocalDate.now();
        int currentYear = today.getYear();
        int currentMonth = today.getMonthValue();
        int lastMonth = today.minusMonths(1).getMonthValue();

        // 1. 从数据库一次性获取全年的数据
        Map<Integer, Integer> inspectionMap = convertToMonthMap(statisticsMapper.getYearlyInspectionCounts(currentYear));
        Map<Integer, Integer> reformMap = convertToMonthMap(statisticsMapper.getYearlyReformCounts(currentYear));
        Map<Integer, Integer> completedReformMap = convertToMonthMap(statisticsMapper.getYearlyCompletedReformCounts(currentYear));
        Map<Integer, Integer> applicableCheckMap = convertToMonthMap(statisticsMapper.getYearlyApplicableCheckCounts(currentYear));
        Map<Integer, Integer> nonCompliantMap = convertToMonthMap(statisticsMapper.getYearlyNonCompliantCheckCounts(currentYear));

        List<SirStatisticsDTO> resultList = new ArrayList<>();

        // 2. 计算并组装四个指标对象
        resultList.add(buildInspectionStats(currentMonth, lastMonth, inspectionMap));
        resultList.add(buildReformStats(currentMonth, lastMonth, reformMap));
        resultList.add(buildRectificationRateStats(currentMonth, lastMonth, reformMap, completedReformMap));
        resultList.add(buildComplianceRateStats(currentMonth, lastMonth, applicableCheckMap, nonCompliantMap));

        return resultList;
    }

    /**
     * 构建 "本月检查数量" 指标
     */
    private SirStatisticsDTO buildInspectionStats(int currentMonth, int lastMonth, Map<Integer, Integer> yearlyData) {
        String name = "本月检查数量";
        Integer currentValue = yearlyData.getOrDefault(currentMonth, 0);
        Integer lastMonthValue = yearlyData.getOrDefault(lastMonth, 0);
        String percent = calculatePercentChange(currentValue, lastMonthValue);
        List<Integer> data = buildMonthlyDataArray(yearlyData);
        return new SirStatisticsDTO(name, currentValue, percent, data);
    }

    /**
     * 构建 "本月整改问题数量" 指标
     */
    private SirStatisticsDTO buildReformStats(int currentMonth, int lastMonth, Map<Integer, Integer> yearlyData) {
        String name = "本月整改问题数量";
        Integer currentValue = yearlyData.getOrDefault(currentMonth, 0);
        Integer lastMonthValue = yearlyData.getOrDefault(lastMonth, 0);
        String percent = calculatePercentChange(currentValue, lastMonthValue);
        List<Integer> data = buildMonthlyDataArray(yearlyData);
        return new SirStatisticsDTO(name, currentValue, percent, data);
    }

    /**
     * 构建 "本月整改率" 指标
     */
    private SirStatisticsDTO buildRectificationRateStats(int currentMonth, int lastMonth, Map<Integer, Integer> totalMap, Map<Integer, Integer> completedMap) {
        String name = "本月整改率";
        Integer currentRate = calculateRate(completedMap.getOrDefault(currentMonth, 0), totalMap.getOrDefault(currentMonth, 0));
        Integer lastMonthRate = calculateRate(completedMap.getOrDefault(lastMonth, 0), totalMap.getOrDefault(lastMonth, 0));
        String percent = calculatePercentChange(currentRate, lastMonthRate);

        List<Integer> data = new ArrayList<>();
        for (int i = 1; i <= 12; i++) {
            data.add(calculateRate(completedMap.getOrDefault(i, 0), totalMap.getOrDefault(i, 0)));
        }
        return new SirStatisticsDTO(name, currentRate, percent, data);
    }

    /**
     * 构建 "本月合格率" 指标
     */
    private SirStatisticsDTO buildComplianceRateStats(int currentMonth, int lastMonth, Map<Integer, Integer> applicableMap, Map<Integer, Integer> nonCompliantMap) {
        String name = "本月合格率";
        // 合格率 = 100 - (不符合 / (符合+不符合+不适用)) * 100
        Integer currentNonComplianceRate = calculateRate(nonCompliantMap.getOrDefault(currentMonth, 0), applicableMap.getOrDefault(currentMonth, 0));
        Integer currentRate = 100 - currentNonComplianceRate;

        Integer lastMonthNonComplianceRate = calculateRate(nonCompliantMap.getOrDefault(lastMonth, 0), applicableMap.getOrDefault(lastMonth, 0));
        Integer lastMonthRate = 100 - lastMonthNonComplianceRate;

        String percent = calculatePercentChange(currentRate, lastMonthRate);

        List<Integer> data = new ArrayList<>();
        for (int i = 1; i <= 12; i++) {
            int nonComplianceRate = calculateRate(nonCompliantMap.getOrDefault(i, 0), applicableMap.getOrDefault(i, 0));
            data.add(100 - nonComplianceRate);
        }
        return new SirStatisticsDTO(name, currentRate, percent, data);
    }

    /**
     * 将数据库查询出的List<Map>转换为更易于使用的 Map<Integer, Integer>
     */
    private Map<Integer, Integer> convertToMonthMap(List<Map<String, Object>> list) {
        return list.stream().collect(Collectors.toMap(
                m -> ((Number) m.get("month")).intValue(),
                m -> ((Number) m.get("count")).intValue()
        ));
    }

    /**
     * 构建1到12月的年度数据数组
     */
    private List<Integer> buildMonthlyDataArray(Map<Integer, Integer> yearlyData) {
        return IntStream.rangeClosed(1, 12)
                .map(month -> yearlyData.getOrDefault(month, 0))
                .boxed()
                .collect(Collectors.toList());
    }

    /**
     * 计算百分比变化
     */
    private String calculatePercentChange(Integer current, Integer previous) {
        if (previous == null || previous == 0) {
            return "+100%"; // 如果上期为0，则视为增长100%
        }
        if (current == null) current = 0;

        BigDecimal change = new BigDecimal(current)
                .subtract(new BigDecimal(previous))
                .divide(new BigDecimal(previous), 2, RoundingMode.HALF_UP)
                .multiply(new BigDecimal(100));

        return (change.doubleValue() >= 0 ? "+" : "") + change.intValue() + "%";
    }

    /**
     * 计算比率，返回整数百分比
     */
    private Integer calculateRate(Integer numerator, Integer denominator) {
        if (denominator == null || denominator == 0) {
            return 0;
        }
        if (numerator == null) numerator = 0;

        return new BigDecimal(numerator)
                .multiply(new BigDecimal(100))
                .divide(new BigDecimal(denominator), 0, RoundingMode.HALF_UP)
                .intValue();
    }

    @Override
    public List<SirWeeklyChecksDTO> getWeeklyCheckStatistics() {
        LocalDate today = LocalDate.now();

        // 计算本周的起止日期 (周一到周日)
        LocalDate thisWeekStart = today.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY));
        LocalDate thisWeekEnd = today.with(TemporalAdjusters.nextOrSame(DayOfWeek.SUNDAY));

        // 计算上周的起止日期
        LocalDate lastWeekStart = thisWeekStart.minusWeeks(1);
        LocalDate lastWeekEnd = thisWeekEnd.minusWeeks(1);

        // 获取上周和本周的数据
        SirWeeklyChecksDTO lastWeekData = getChecksForWeek(lastWeekStart, lastWeekEnd);
        SirWeeklyChecksDTO thisWeekData = getChecksForWeek(thisWeekStart, thisWeekEnd);

        // 按照[上周, 本周]的顺序返回
        return Stream.of(lastWeekData, thisWeekData).collect(Collectors.toList());
    }

    /**
     * 根据指定的起止日期，查询并组装一周的检查数据
     * @param startDate 周一的日期
     * @param endDate 周日的日期
     * @return 组装好的一周统计数据对象
     */
    private SirWeeklyChecksDTO getChecksForWeek(LocalDate startDate, LocalDate endDate) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        String startStr = startDate.format(formatter) + " 00:00:00";
        String endStr = endDate.format(formatter) + " 23:59:59";

        // 从数据库获取数据
        List<Map<String, Object>> dailyStats = statisticsMapper.getDailyCheckStats(startStr, endStr);

        // 将List转换为Map，方便按日期查找
        Map<LocalDate, Map<String, Object>> statsByDate = dailyStats.stream()
                .collect(Collectors.toMap(
                        row -> ((java.sql.Date) row.get("check_date")).toLocalDate(),
                        row -> row
                ));

        List<Integer> totalChecks = new ArrayList<>();
        List<Integer> compliantChecks = new ArrayList<>();

        // 循环一周七天，填充数据
        for (int i = 0; i < 7; i++) {
            LocalDate currentDate = startDate.plusDays(i);
            Map<String, Object> dayStats = statsByDate.get(currentDate);

            if (dayStats != null) {
                // 如果当天有数据，则使用数据库的数据
                totalChecks.add(((Number) dayStats.get("total_checks")).intValue());
                compliantChecks.add(((Number) dayStats.get("compliant_checks")).intValue());
            } else {
                // 如果当天无数据，则填充0
                totalChecks.add(0);
                compliantChecks.add(0);
            }
        }

        SirWeeklyChecksDTO weeklyData = new SirWeeklyChecksDTO();
        weeklyData.setRequireData(totalChecks);
        weeklyData.setQuestionData(compliantChecks);

        return weeklyData;
    }

    @Override
    public List<SirWeeklyComplianceDTO> getWeeklyComplianceStatistics() {
        LocalDate today = LocalDate.now();
        // 获取本周的周一
        LocalDate monday = today.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY));
        // 获取本周的周日
        LocalDate sunday = today.with(TemporalAdjusters.nextOrSame(DayOfWeek.SUNDAY));

        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        String startStr = monday.format(formatter) + " 00:00:00";
        String endStr = sunday.format(formatter) + " 23:59:59";

        // 1. 从数据库一次性获取本周的数据
        List<Map<String, Object>> dailyStats = statisticsMapper.getDailyComplianceStats(startStr, endStr);
        Map<LocalDate, Map<String, Object>> statsByDate = dailyStats.stream()
                .collect(Collectors.toMap(
                        row -> ((java.sql.Date) row.get("check_date")).toLocalDate(),
                        row -> row
                ));

        // 2. 准备常量和结果列表
        List<SirWeeklyComplianceDTO> result = new ArrayList<>();
        String[] weekDays = {"周一", "周二", "周三", "周四", "周五", "周六", "周日"};
        final String GREEN_COLOR = "#26ce83";
        final String RED_COLOR = "#ff4141"; // 红色
        final int DURATION = 3000;

        // 3. 遍历本周七天，计算并组装数据
        for (int i = 0; i < 7; i++) {
            LocalDate currentDate = monday.plusDays(i);
            Map<String, Object> dayStats = statsByDate.get(currentDate);

            int percentage = 0;
            if (dayStats != null) {
                // 读取适用检查总数和合格检查数
                int applicableChecks = ((Number) dayStats.get("applicable_checks")).intValue();
                int compliantChecks = ((Number) dayStats.get("compliant_checks")).intValue();

                // 安全地计算百分比，避免除以零的错误
                if (applicableChecks > 0) {
                    percentage = new BigDecimal(compliantChecks)
                            .multiply(new BigDecimal(100))
                            .divide(new BigDecimal(applicableChecks), 0, RoundingMode.HALF_UP)
                            .intValue();
                }
            }

            // 根据百分比决定颜色
            String color = (percentage > 90) ? GREEN_COLOR : RED_COLOR;

            // 创建DTO并添加到结果列表
            result.add(new SirWeeklyComplianceDTO(weekDays[i], percentage, DURATION, color));
        }

        return result;
    }


    @Override
    public List<SirDailySummaryDTO> getDailySummaryForLast30Days() {
        LocalDate today = LocalDate.now();
        LocalDate startDate = today.minusDays(29);
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");

        String startStr = startDate.format(formatter) + " 00:00:00";
        String endStr = today.format(formatter) + " 23:59:59";

        // 1. 从数据库分表获取数据
        List<Map<String, Object>> checkData = statisticsMapper.getDailyCheckSummary(startStr, endStr);
        List<Map<String, Object>> reportData = statisticsMapper.getDailyReportSummary(startStr, endStr);
        List<Map<String, Object>> reformData = statisticsMapper.getDailyReformSummary(startStr, endStr);

        // 2. 将List转换为Map以便快速查找
        Function<Map<String, Object>, LocalDate> keyMapper = row -> ((java.sql.Date) row.get("stat_date")).toLocalDate();
        Map<LocalDate, Map<String, Object>> checkMap = checkData.stream().collect(Collectors.toMap(keyMapper, Function.identity()));
        Map<LocalDate, Map<String, Object>> reportMap = reportData.stream().collect(Collectors.toMap(keyMapper, Function.identity()));
        Map<LocalDate, Map<String, Object>> reformMap = reformData.stream().collect(Collectors.toMap(keyMapper, Function.identity()));

        // 3. 循环30天，组装最终结果
        List<SirDailySummaryDTO> resultList = new ArrayList<>();
        for (int i = 0; i < 30; i++) {
            LocalDate currentDate = today.minusDays(i);
            SirDailySummaryDTO dailySummary = new SirDailySummaryDTO();
            dailySummary.setId(30 - i);
            dailySummary.setDate(currentDate.format(formatter));

            // 获取当天的各项统计数据，如果不存在则默认为0
            Map<String, Object> currentCheck = checkMap.getOrDefault(currentDate, Map.of());
            Map<String, Object> currentReport = reportMap.getOrDefault(currentDate, Map.of());
            Map<String, Object> currentReform = reformMap.getOrDefault(currentDate, Map.of());

            // 填充数据
            dailySummary.setTotalCheckNum(getValue(currentCheck, "total_checks"));
            dailySummary.setQualifiedNum(getValue(currentCheck, "non_compliant_checks"));
            dailySummary.setReportNum(getValue(currentReport, "report_count"));
            dailySummary.setReformNum(getValue(currentReform, "total_reforms"));
            dailySummary.setReformOverNum(getValue(currentReform, "completed_reforms"));

            // 计算合格率
            int applicableChecks = getValue(currentCheck, "applicable_checks");
            int nonCompliantChecks = dailySummary.getQualifiedNum();
            if (applicableChecks > 0) {
                // 合格率 = (适用数 - 不合格数) / 适用数
                int compliantChecks = applicableChecks - nonCompliantChecks;
                int rate = new BigDecimal(compliantChecks)
                        .multiply(new BigDecimal(100))
                        .divide(new BigDecimal(applicableChecks), 0, RoundingMode.HALF_UP)
                        .intValue();
                dailySummary.setQualifiedRate(rate);
            } else {
                dailySummary.setQualifiedRate(100); // 如果没有适用检查项，合格率为100%
            }

            resultList.add(dailySummary);
        }
        return resultList;
    }

    /**
     * 从Map中安全地获取数值，如果不存在或类型不匹配则返回0
     */
    private int getValue(Map<String, Object> map, String key) {
        Object value = map.get(key);
        if (value instanceof Number) {
            return ((Number) value).intValue();
        }
        return 0;
    }

    @Override
    public List<SirRecentActivityDTO> getRecentActivities() {
        return statisticsMapper.getRecentActivities();
    }
}